#include "chessboard.h"

chessBoard::chessBoard(QWidget *parent)
    : QWidget{parent}, color(BLACK), tcpsock(new QTcpSocket(this))
{
    // 初始化棋盘
    initBoard();

    // 发起网络连接
    tcpsock->connectToHost("120.79.255.109", 8082);
    // 读数据
    connect(tcpsock, &QTcpSocket::readyRead, this, &chessBoard::readData);
    // 发数据
    connect(tcpsock, &QTcpSocket::connected, this, &chessBoard::sendData);
}

void chessBoard::initBoard()
{
    for (int i = 0;i < 15;i++)
    {
        for (int j = 0;j < 15;j++)
        {
            board[i][j] = EMPTY;
        }
    }
}

void chessBoard::paintEvent(QPaintEvent* e)
{
    QPainter painter(this);
    // 绘制背景色
    painter.fillRect(QRect(0, 0, 580, 580), QColor(255, 170, 0));
    // 绘制横线
    for (int i = 0;i < 15;i++)
    {
        painter.drawLine(10, i * 40 + 10, 570, i *  40 + 10);
    }
    // 绘制竖线
    for (int j = 0;j < 15;j++)
    {
        painter.drawLine(j * 40 + 10, 10, j * 40 + 10, 570);
    }
    // 绘制棋子
    for (int i = 0;i < 15;i++)
    {
        for (int j = 0;j < 15;j++)
        {
            if (board[i][j] == BLACK)
            {
                QBrush brush(Qt::black);
                painter.setBrush(brush);
                painter.drawEllipse(QPoint(j * 40 + 10, i * 40 + 10), 10, 10);
            }
            else if (board[i][j] == WHITE)
            {
                QBrush brush(Qt::white);
                painter.setBrush(brush);
                painter.drawEllipse(QPoint(j * 40 + 10, i * 40 + 10), 10, 10);
            }
        }
    }
}

void chessBoard::mousePressEvent(QMouseEvent* event)
{
    int x = event->x();
    int y = event->y();
    qDebug() << "x = " << x;
    // 下棋
    playChess(x, y);
}

void chessBoard::playChess(int x, int y)
{
    QPoint p = transformCoordinate(x, y);
    if (p.x() == INT_MAX)
    {
        QMessageBox::warning(nullptr, "警告", "你下棋的位置不合法!");
        return;
    }
    board[p.y()][p.x()] = color;
    sendCoordinate(p.x(), p.y());
    update();
    int ret = judge(p.y(), p.x(), color);
    if (ret == 5)
    {
        QMessageBox::information(nullptr, "温馨提示", "恭喜您，取得了游戏的胜利!");
        tcpsock->write("game over");
    }
}

QPoint chessBoard::transformCoordinate(int x, int y)
{
    int startx = x - 40;
    int starty = y - 40;
    int endx = x + 40;
    int endy = y + 40;
    if (startx < 0)
    {
        startx = 0;
    }
    if (starty < 0)
    {
        starty = 0;
    }
    if (endx > 580)
    {
        endx = 580;
    }
    if (endy > 580)
    {
        endy = 580;
    }
    for (int i = startx;i <= endx;i++)
    {
        for (int j = starty;j <= endy;j++)
        {
            if ((i - 10) % 40 == 0 && (j - 10) % 40 == 0)
            {
                int tmp = (i - x) * (i - x) + (j - y) * (j - y);
                if (tmp < 100)
                {
                    return QPoint((i - 10) / 40, (j - 10) / 40);
                }
            }
        }
    }
    return QPoint(INT_MAX, INT_MAX);
}

void chessBoard::getColor(QJsonObject obj)
{
    color = obj["color"].toInt() == 1 ? BLACK : WHITE;
    emit showChessColor(color);
}

void chessBoard::sendCoordinate(int x, int y)
{
    QJsonObject obj;
    obj["x"] = x;
    obj["y"] = y;
    obj["color"] = color == BLACK ? 1 : 2;
    QJsonDocument doc(obj);
    QString data = doc.toJson(QJsonDocument::Compact);
    tcpsock->write(data.toStdString().c_str());
}

void chessBoard::readData()
{
    QString data = tcpsock->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(data.toUtf8());
    QJsonObject obj = doc.object();
    if (obj["x"].isNull())
    {
        getColor(obj);
    }
    else
    {
        syncChess(obj["x"].toInt(), obj["y"].toInt(), obj["color"].toInt() == 1 ? BLACK : WHITE);
    }
}

void chessBoard::sendData()
{
    tcpsock->write("1");
}

void chessBoard::syncChess(int x, int y, Piece clr)
{
    board[y][x] = clr;
    update();
    int ret = judge(y, x, clr);
    if (ret == 5)
    {
        QMessageBox::information(nullptr, "温馨提示", "很抱歉，游戏失败了!");
    }
}

int chessBoard::_judge(int row, int col, int rowd, int cold, Piece color)
{
    int count = 1;
    int step = 0;
    while (step < 4)
    {
        row += rowd;
        col += cold;
        // 坐标非法
        if (row < 0 || row > 14 || col < 0 || col > 14)
        {
            break;
        }
        if (board[row][col] == color)
        {
            count++;
        }
        else
        {
            break;
        }
        step++;
    }
    return count;
}

int chessBoard::judge(int row, int col, Piece color)
{
    std::vector<int> results(8, -1);
    results[0] = _judge(row, col, -1, -1, color);
    results[1] = _judge(row, col, -1, 0, color);
    results[2] = _judge(row, col, -1, 1, color);
    results[3] = _judge(row, col, 0, 1, color);
    results[4] = _judge(row, col, 1, 1, color);
    results[5] = _judge(row, col, 1, 0, color);
    results[6] = _judge(row, col, 1, -1, color);
    results[7] = _judge(row, col, 0, -1, color);
    int max_cnt = -1;
    for (int i = 0;i < 8;i++)
    {
        if (results[i] > max_cnt)
        {
            max_cnt = results[i];
        }
    }
    return max_cnt;
}
